跳到主要内容

react router简介

API 分类

react router中的 API 分为以下三类:

  • 基础路由组件,用于全局处理路由转发任务,包括BrowserRouterHashRouter
  • 路由匹配组件,用于根据 URL 匹配指定的页面组件,包括RouteSwitch
  • 页面跳转组件,包括LinkNavLinkRedirect,最终会转换成a标签嵌入页面

BrowserRouter 和 HashRouter

BrowserRouterHashRouter作为基础组件,通常作为跟组件包裹整个应用。它们俩的不同是HashRouter会将当前页面配置的路由路径显示在 URL 的hash部分,因此 URL 看起来像xxx.com/path#user/xxxx,单页面应用来说这点其实没什么影响,但是对于SSR(server side render)的应用,改变 URL 的path会向服务端发送请求 HTML 页面,而改变hash并不会发送请求。

import { BrowserRouter } from 'react-router-dom';

ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root'),
);

Switch 和 Route

Switch用来包裹一系列的Route组件,当 URL 改变的时候,Switch组件会搜索子组件中的Route,根据给定的path属性来匹配当前的 URL,当匹配到第一个时就会停止匹配。如果不用Switch包裹Route,那么Route指定的组件将都会被渲染出来。

function App() {
return (
<div>
<Switch>
<Route path="/about">
<About />
</Route>
<Route path="/contact/:id">
<Contact />
</Route>
</Switch>
</div>
);
}

Route

Route组件是最主要的用来配置 URL 路径以及根据路由渲染组件。其中path属性必传,其余还有三种引入组件的方式:componentrenderchildren

path

首先path也就是最终推送到 URL 的路径部分属性,支持传入一个字符串或者字符串数组,字符串数组也就是多个路径匹配到同一个显示的页面组件。字符串的形式支持根据path-to-regexp@^1.7.0的形式,常见的有:

  • /:xxx指定 URL 的pathname部分的参数

path配合使用的属性还有exactstrictsensitive

  • exact:是否必须精准匹配当前的location.pathname部分,例如当指定exact的时候,/one只会匹配location.pathname = one的 URL,后面如果再串接一个子路径就不会被匹配。

  • strict:是否精准匹配 URL 的location.pathname最后的斜杠,例如当指定strict的时候,/one/只会匹配/one/而不会匹配/one,但是当location.pathname包含子路径的时候,strict就无效了,也就是此时/one/也会匹配/one/two

  • sensitive:是否大小写敏感

component

component属性直接接收一个组件。需要注意的是,Route内部对component的处理是直接使用React.createElement来创建一个新的组件,一旦组件接收的props发生改变,那么就会导致整个组件卸载重新创建一个新的组件替换上去,而不是使用 DIFF 算法更新原来的组件,此举会带来轻微的性能问题。

function User(props) {
return <h1>Hello {props.match.params.username}!</h1>;
}

ReactDOM.render(
<Router>
<Route path="/user/:username" component={User} />
</Router>,
node,
);

render

render就是利用 render props 的概念,传入一个函数属性,该函数返回一个组件,在Route匹配的时候直接调用函数渲染组件。

由于 render props 概念的特殊性,该函数可以轻易改造称为一个高阶组件,即将render函数的参数直接通过props传入到组件本身即可,这样组件内部也会获得react routermatch, locationhistory这些属性。

function FadingRoute({ component: Component, ...rest }) {
return (
<Route
{...rest}
render={routeProps => (
<FadeIn>
<Component {...routeProps} />
</FadeIn>
)}
/>
);
}

children

children也是一个函数,和render函数的区别就是如果当前location没有匹配到当前的Route配置,那么children函数接收的参数中的match属性会是null,根据这个可以动态的为组件增加一些个性化的定制,例如最为常见的根据 URL 动态的渲染Menu组件的样式:

function ListItemLink({ to, ...rest }) {
return (
<Route
path={to}
children={({ match }) => (
<li className={match ? 'active' : ''}>
<Link to={to} {...rest} />
</li>
)}
/>
);
}

ReactDOM.render(
<BrowserRouter>
<ul>
<ListItemLink to="/somewhere" />
<ListItemLink to="/somewhere-else" />
</ul>
</BrowserRouter>,
node,
);

Link组件可以用于页面跳转链接生成,其可以接受以下属性:

to

to可以是路由路径字符串,也可以是一个location对象,或者是一个函数,函数会接受location对象作为参数,必须返回一个新的路径字符串或者location对象。

replace

指定使用history.replace来进行跳转

Redirect

to

同上Link

from

值得一提的是Redirect表示重定向操作,这个组件可以和Switch结合,通过指定from传递一个希望重定向的路径,会在Switch匹配到from指定的路径后,自动跳转到to指定的新的 URL。

路由对象

react router对 HTML 的historylocation对象进行了一些改造,并在通过Routerender或者children渲染组件时,以render props以及高阶组件的形式将这些对象注入到组件中。

history

react routerhistory对象与 HTML 本身提供的History接口的对象属性不同,其具有一定改造后的属性和方法,相比 HTML 原生 API 更加方便开发使用。具体来说,其具有以下属性和方法:

  • length:历史记录堆栈长度
  • action:当前执行的操作方法名称,PUSH, REPLACE, 或POP
  • location:具有以下属性
    • pathname:URL 的path部分
    • search: URL 的 queryString 部分
    • hash: URL 的 hash 部分
    • state:当前状态数据,例如通过执行push(path, state)方法
  • push(path, [state]):跳转路由
  • replace(path, [state]):跳转路由,与push不同的是,被replace替换掉的当前页面不会保存在历史记录中
  • go(n):根据历史记录的堆栈索引跳转页面,go(-1)也就是返回
  • goBack():返回上一页
  • goForward():前进一页

对应的可以通过useHistory获取这个history对象。

location

单独拎出来的locationhistory具有一样的属性,不同的是history.location是禁止修改的对象,但是location可以。

对应的,可以通过useLocation来获取这个location对象。

match

match包含与 URL 匹配的当前Route指定的一些属性:

  • params:从 URL 的参数部分解析出来的一个对象,键是通过Routepath指定的参数匹配字符串,值也就是当前在 URL 里传递进去的值;例如当前 URL 为/user/1234,对应匹配的Route指定的path应该是/user/:id,那么此时params就是{ id: 1234 }

  • isExact:如果是整个 URL 都匹配当前Route,则该值为true

  • path:当前匹配的Route中指定的path

  • url:URL 中匹配Route中指定的path的该部分内容

可以使用useParams来获取matchparams属性,解析出 URL 中pathname的参数值。

useRouteMatch | hook

useRouteMatch可以接收和Route组件相同的属性作为参数,用来匹配当前 URL,如果成功匹配则返回match对象,否则返回null

withRouter

withRouter是一个高阶组件,通过包裹指定组件,组件内部可以自动获得historylocationmatch这些对象。

滚动位置恢复

React Router: Declarative Routing for React.js